{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c101c366-e90c-489a-a18a-ed9bad56709f",
   "metadata": {},
   "source": [
    "# 在链上使用记忆\n",
    "- LLMChain\n",
    "- ConversationChain\n",
    "- 自定义\n",
    "- 同一个链合并使用多个记忆\n",
    "- 给一个多参数链增加记忆"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6593e75-6131-419a-a3ca-c984d5c80990",
   "metadata": {},
   "source": [
    "## LLMChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4c12f393-011c-4ae4-bd14-ba476ec952f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import LLMChain\n",
    "from langchain.llms import OpenAI\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "#自定义模板\n",
    "template = \"\"\"你是一个可以和人类对话的机器人.\n",
    "{chat_history}\n",
    "人类:{human_input}\n",
    "机器人:\n",
    "\"\"\"\n",
    "\n",
    "prompt= PromptTemplate(\n",
    "    template=template,\n",
    "    input_variables=[\"chat_history\", \"human_input\"],\n",
    ")\n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key=\"chat_history\",\n",
    ")\n",
    "llm = OpenAI(\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "chain = LLMChain(\n",
    "    llm=llm,\n",
    "    memory=memory,\n",
    "    prompt=prompt,\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "chain.predict(human_input=\"你好，我叫tom\")\n",
    "chain.predict(human_input=\"我最新喜欢我的世界这个游戏，你还记得我叫什么吗？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71e13016-c726-4dd6-8fc6-a501fe3a86f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import  ChatOpenAI\n",
    "from langchain.prompts import  (\n",
    "    ChatPromptTemplate,\n",
    "    HumanMessagePromptTemplate,\n",
    "    MessagesPlaceholder,\n",
    ")\n",
    "from langchain.schema import  SystemMessage\n",
    "\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        SystemMessage(\n",
    "            content=\"你好，我是一个可以和人类对话的机器人\",\n",
    "            role=\"system\",\n",
    "        ),\n",
    "        MessagesPlaceholder(\n",
    "            variable_name=\"chat_history\", # 这里放置聊天记录\n",
    "        ),\n",
    "        HumanMessagePromptTemplate.from_template(\n",
    "            \"{human_input}\"\n",
    "        ),\n",
    "    ]\n",
    ")\n",
    "print(prompt.format(human_input=\"你好\",chat_history=[]))\n",
    "\n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key=\"chat_history\",\n",
    "    return_messages=True,\n",
    ")\n",
    "llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "chain = LLMChain(\n",
    "    llm=llm,\n",
    "    memory=memory,\n",
    "    prompt=prompt,\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "chain.predict(human_input=\"我叫tomie，我是一个AI应用程序猿\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c290abf-97f6-4fa9-aa36-050c977f560b",
   "metadata": {},
   "source": [
    "## ConversationChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9738e0bb-4fa8-4383-a48c-73d450c6945c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import ConversationChain\n",
    "from langchain.llms import OpenAI\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "\n",
    "llm=OpenAI(\n",
    "    temperature=0,\n",
    ")\n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key=\"history\",\n",
    "    return_messages=True,\n",
    ")\n",
    "chain = ConversationChain(\n",
    "    llm=llm,\n",
    "    memory=memory,\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "chain.predict(input=\"今天天气如何\")\n",
    "chain.predict(input=\"帮我做个一日游攻略\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5df27907-857f-460c-a7c7-a6764154c630",
   "metadata": {},
   "outputs": [],
   "source": [
    "#自定义一下，对其进行覆盖\n",
    "from langchain.chains import ConversationChain\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "from langchain.prompts import PromptTemplate\n",
    "from langchain.llms import OpenAI\n",
    "\n",
    "llm=OpenAI(\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "template = \"\"\"下面是一段AI与人类的对话，AI会针对人类问题，提供尽可能详细的回答，如果AI不知道答案，会直接回复'人类老爷，我真的不知道'.\n",
    "当前对话:\n",
    "{history}\n",
    "Human:{input}\n",
    "AI助手:\"\"\"\n",
    "\n",
    "prompt = PromptTemplate(\n",
    "    template=template,\n",
    "    input_variables=[\"history\", \"input\"],\n",
    ")\n",
    "\n",
    "chain = ConversationChain(\n",
    "    llm=llm,\n",
    "    memory=ConversationBufferMemory(\n",
    "        ai_prefix=\"AI助手\",\n",
    "        return_messages=True,\n",
    "    ),\n",
    "    prompt=prompt,\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "chain.predict(input=\"今天天气如何\")\n",
    "chain.predict(input=\"帮我做个一日游攻略\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d01199c-a702-4f66-8d3c-7a245f0a1401",
   "metadata": {},
   "source": [
    "## 同一个链合并使用多个memory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5042086f-2b48-497a-964e-ae9b099d4084",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import ConversationChain\n",
    "from langchain.llms import OpenAI\n",
    "from langchain.memory import (\n",
    "    ConversationBufferMemory,\n",
    "    ConversationSummaryMemory,\n",
    "    CombinedMemory\n",
    ")\n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "llm = OpenAI(\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "#使用CoversationSummaryMemory对对话进行总结\n",
    "summay = ConversationSummaryMemory(\n",
    "    llm=llm,\n",
    "    input_key=\"input\"\n",
    ")\n",
    "#使用ConversationBufferMemory对对话进行缓存\n",
    "cov_memory = ConversationBufferMemory(\n",
    "    memory_key=\"history_now\",\n",
    "    input_key=\"input\",\n",
    ")\n",
    "\n",
    "memory = CombinedMemory(\n",
    "    memories=[summay, cov_memory],\n",
    ")\n",
    "\n",
    "TEMPLATE = \"\"\"下面是一段AI与人类的对话，AI会针对人类问题，提供尽可能详细的回答，如果AI不知道答案，会直接回复'人类老爷，我真的不知道'.\n",
    "之前的对话摘要:\n",
    "{history}\n",
    "当前对话:\n",
    "{history_now}\n",
    "Human:{input}\n",
    "AI：\"\"\"\n",
    "\n",
    "prompt = PromptTemplate(\n",
    "    template=TEMPLATE,\n",
    "    input_variables=[\"history\", \"history_now\", \"input\"],\n",
    ")\n",
    "\n",
    "chain = ConversationChain(\n",
    "    llm=llm,\n",
    "    memory=memory,\n",
    "    prompt=prompt,\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "chain.run(\"你对加密市场如何分析？\")\n",
    "chain.run(\"那ETH呢？\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc71f943-7b2c-4583-b0ff-a04699c98b2d",
   "metadata": {},
   "source": [
    "## 多参数链增加记忆"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19b5874a-d548-4b14-a525-1ba26178a1c3",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.embeddings.openai import  OpenAIEmbeddings\n",
    "from langchain.text_splitter import CharacterTextSplitter\n",
    "from langchain.vectorstores import Chroma\n",
    "\n",
    "with open(\"letter.txt\") as f:\n",
    "    text = f.read()\n",
    "    #切分文本\n",
    "    text_splitter = CharacterTextSplitter(\n",
    "        chunk_size = 20,\n",
    "        chunk_overlap = 5\n",
    "    )\n",
    "    texts = text_splitter.split_text(text)\n",
    "\n",
    "    #使用openai的embedding\n",
    "    embddings = OpenAIEmbeddings()\n",
    "    #使用chroma向量存储\n",
    "    docssearch = Chroma.from_texts(\n",
    "        texts,\n",
    "        embddings,\n",
    "    )\n",
    "    query = \"公司有什么新策略?\"\n",
    "    docs = docssearch.similarity_search(query=query)\n",
    "\n",
    "#构建问答对话链\n",
    "from langchain.chains.question_answering import  load_qa_chain\n",
    "from langchain.llms import OpenAI\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "llm = OpenAI(\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "template = \"\"\"下面是一段AI与人类的对话，AI会针对人类问题，提供尽可能详细的回答，如果AI不知道答案，会直接回复'人类老爷，我真的不知道'，参考一下相关文档以及历史对话信息，AI会据此组织最终回答内容.\n",
    "{context}\n",
    "{chat_history}\n",
    "Human:{human_input}\n",
    "AI:\"\"\"\n",
    "\n",
    "prompt = PromptTemplate(\n",
    "    template=template,\n",
    "    input_variables=[\"context\", \"chat_history\", \"human_input\"],\n",
    ")\n",
    "\n",
    "#使用ConversationBufferMemory对对话进行缓存 \n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key=\"chat_history\",\n",
    "    input_key=\"human_input\",\n",
    "    return_messages=True,\n",
    ")\n",
    "\n",
    "#加载对话链\n",
    "chain = load_qa_chain(\n",
    "    llm=llm,\n",
    "    memory=memory,\n",
    "    prompt=prompt,\n",
    "    verbose=True,\n",
    "    chain_type=\"stuff\"\n",
    ")\n",
    "\n",
    "chain({\"input_documents\":docs,\"human_input\":\"公司的营销策略是什么？\"})"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (langchain)",
   "language": "python",
   "name": "langchain-env"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
